package aoi

import "sanguo/node/node_map"

//"fmt"

type AOI struct {
	grid *GridMgr
}

func New(leftBottom, rightTop Position, splitCount int32) *AOI {
	grid := NewGridMgr(leftBottom, rightTop, splitCount)
	if nil == grid {
		return nil
	} else {
		return &AOI{
			grid: grid,
		}
	}
}

func (this *AOI) Add(obj AOIObject) bool {

	if nil != obj.GetGrid() {
		return false
	}

	grid := this.grid.GetGridByPos(obj.GetAoiPosition())

	if nil == grid {
		return false
	}

	grid.aoiObjs[obj] = true
	obj.SetGrid(grid)

	obj.AddObserver(obj)

	grids := this.grid.GetNearBy(grid)

	for _, v := range grids {
		for o, _ := range v.aoiObjs {
			if o != obj {
				o.AddObserver(obj)
				obj.AddObserver(o) //o成为obj的观察者
			}
		}
	}

	return true
}

func (this *AOI) Remove(obj AOIObject) bool {

	grid := obj.GetGrid()

	if nil == grid {
		node_map.Debugln("remove grid nil")
		return false
	}

	obj.ForEachObserver(func(o AOIObject) {
		//向obj的所有观察者通告obj离开视野
		o.RemoveObserver(obj)
	})

	obj.ClearObjserver()
	delete(grid.aoiObjs, obj)
	obj.SetGrid(nil)

	return true

}

//获取obj可以看到的所有其它对象
func (this *AOI) GetViewObjs(obj AOIObject) []AOIObject {
	if nil != obj.GetGrid() {
		return nil
	}

	grid := this.grid.GetGridByPos(obj.GetAoiPosition())

	if nil == grid {
		return nil
	}

	ret := make([]AOIObject, 100)

	grids := this.grid.GetNearBy(grid)

	for _, v := range grids {
		for o, _ := range v.aoiObjs {
			ret = append(ret, o)
		}
	}

	return ret
}

func inRange(leftTop, rightBottom *Grid, grid *Grid) bool {

	//fmt.Println(leftTop,rightBottom,grid)

	if grid.c < leftTop.c {
		return false
	}

	if grid.r < leftTop.r {
		return false
	}

	if grid.c > rightBottom.c {
		return false
	}

	if grid.r > rightBottom.r {
		return false
	}

	return true
}

func (this *AOI) Update(obj AOIObject) {

	oldGrid := obj.GetGrid()
	if oldGrid == nil {
		node_map.Infoln("olsGrid is nil")
		return
	}

	newGrid := this.grid.GetGridByPos(obj.GetAoiPosition())
	if newGrid == oldGrid {
		node_map.Infoln("oldGrid == newGrid")
		return
	}

	oldGrids := this.grid.GetNearBy(oldGrid)
	newGrids := this.grid.GetNearBy(newGrid)

	delete(oldGrid.aoiObjs, obj)
	newGrid.aoiObjs[obj] = true
	obj.SetGrid(newGrid)

	for _, v := range oldGrids {

		//fmt.Println("n",len(newGrids)-1,newGrids[len(newGrids)-1])

		//离开的网格
		if !inRange(newGrids[0], newGrids[len(newGrids)-1], v) {
			for o, _ := range v.aoiObjs {
				o.RemoveObserver(obj)
				obj.RemoveObserver(o)
			}
		}
	}

	for _, v := range newGrids {
		//新进入的网格
		if !inRange(oldGrids[0], oldGrids[len(oldGrids)-1], v) {
			for o, _ := range v.aoiObjs {
				if o != obj {
					o.AddObserver(obj)
					obj.AddObserver(o)
				}
			}
		}
	}

	obj.OnAoiUpdate()

}
